package com.example.high_slope_electronic_sand_table.seepagePressure.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.example.high_slope_electronic_sand_table.common.constant.DataClassificationConstant;
import com.example.high_slope_electronic_sand_table.common.constant.GeneralConstants;
import com.example.high_slope_electronic_sand_table.common.util.WeightRandomUtil;
import com.example.high_slope_electronic_sand_table.seepagePressure.Enum.SeepagePressureWarningEnum;
import com.example.high_slope_electronic_sand_table.seepagePressure.dto.SeepagePressureMonitorDTO;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SeepagePressureMonitorService {
    private final static String DEVICE_SN_MIDDLE = "0SPM0"; // 设备编码中段

    private final static Integer MAX_SIZE = 30; // 最大数据条数

    private static Map<String, List<SeepagePressureMonitorDTO>> seepagePressureMonitorDataMap = new HashMap<>();

    /**
     * 查询单条渗流压力监测-渗流压力数据
     *
     * @return
     */
    public SeepagePressureMonitorDTO getCurrentMonitorData(String deviceId) {
        if (!seepagePressureMonitorDataMap.containsKey(deviceId) || seepagePressureMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        // 获取当前的时间和当前设备数据最后一条时间比较，如果当前时间比数据最后一条时间大于等于10分钟，则重新生成一条数据放在列表最后。如果小于十分钟，返回最后一条数据
        LocalDateTime currentDateTime = LocalDateTime.now();
        SeepagePressureMonitorDTO seepagePressureMonitorDTO = seepagePressureMonitorDataMap.get(deviceId).get(MAX_SIZE - 1);
        LocalDateTime lastDateTime = LocalDateTime.parse(seepagePressureMonitorDTO.getDatetime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
        Duration duration = Duration.between(lastDateTime, currentDateTime);
        if (duration.toMinutes() >= GeneralConstants.GENERATOR_DATA_DURATION_TIME) {
            for (int item = 1; item <= duration.toMinutes() / GeneralConstants.GENERATOR_DATA_DURATION_TIME; item++) {
                Date newDate = DateUtil.offset(Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant()), DateField.MINUTE, +item * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 最后一条时间向后推10分钟
                seepagePressureMonitorDataMap.get(deviceId).add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
                seepagePressureMonitorDataMap.get(deviceId).remove(0);
            }
            return seepagePressureMonitorDataMap.get(deviceId).get(MAX_SIZE - 1);
        } else {
            return seepagePressureMonitorDTO;
        }
    }

    /**
     * 查询某个设备所有渗流压力监测-渗流压力数据
     *
     * @return
     */
    public List<SeepagePressureMonitorDTO> listMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!seepagePressureMonitorDataMap.containsKey(deviceId) || seepagePressureMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return seepagePressureMonitorDataMap.get(deviceId).stream().sorted(Comparator.comparing(SeepagePressureMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 查询某个设备所有渗流压力监测-渗流压力告警数据
     *
     * @return
     */
    public List<SeepagePressureMonitorDTO> listWarningMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!seepagePressureMonitorDataMap.containsKey(deviceId) || seepagePressureMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return seepagePressureMonitorDataMap.get(deviceId).stream()
                .sorted(Comparator.comparing(SeepagePressureMonitorDTO::getDatetime).reversed())
                .filter(seepagePressureMonitorDTO -> seepagePressureMonitorDTO.getSeepagePressureWarningLevel() != 0)
                .collect(Collectors.toList());
    }


    /**
     * 查询多条渗流压力监测-渗流压力数据
     *
     * @return
     */
    public List<SeepagePressureMonitorDTO> listMonitorData() {
        List<SeepagePressureMonitorDTO> seepagePressureMonitorDTOS = new ArrayList<>();
        if (seepagePressureMonitorDataMap.isEmpty()) {
            // 生成3个设备相关数据
            for (int index = 0; index < GeneralConstants.GENERATOR_DEVICE_NUMBER; index++) {
                String deviceId = GeneralConstants.DEVICE_SN_PREFIX + DEVICE_SN_MIDDLE + index;
                batchGeneratorMonitorDataS(deviceId);
            }
        }
        for (String deviceId : seepagePressureMonitorDataMap.keySet()) {
            seepagePressureMonitorDTOS.addAll(seepagePressureMonitorDataMap.get(deviceId));
        }
        return seepagePressureMonitorDTOS.stream().sorted(Comparator.comparing(SeepagePressureMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 批量生成渗流压力监测-渗流压力数据
     *
     * @param deviceId
     */
    private void batchGeneratorMonitorDataS(String deviceId) {
        List<SeepagePressureMonitorDTO> seepagePressureMonitorDTOS = new ArrayList<>(MAX_SIZE);
        for (int item = 1; item <= MAX_SIZE; item++) {
            Date date = DateUtil.date();
            Date newDate = DateUtil.offset(date, DateField.MINUTE, -(MAX_SIZE - item) * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 当前时间向前推item*10分钟
            seepagePressureMonitorDTOS.add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
        }
        seepagePressureMonitorDataMap.put(deviceId, seepagePressureMonitorDTOS);
    }

    /**
     * 生成渗流压力监测-渗流压力数据
     *
     * @param deviceId
     * @param dateTime
     * @return
     */
    private SeepagePressureMonitorDTO generatorMonitorData(String deviceId, String dateTime) {
        SeepagePressureMonitorDTO seepagePressureMonitorDTO = new SeepagePressureMonitorDTO();
        seepagePressureMonitorDTO.setDeviceId(deviceId);
        // 生成权重随机数
        Float seepagePressureValue = WeightRandomUtil.getWeightRandomValue(SeepagePressureWarningEnum.WARNING_ONE.getValue(),
                SeepagePressureWarningEnum.WARNING_TWO.getValue(), SeepagePressureWarningEnum.WARNING_THREE.getValue(),
                0f, 2f);
        seepagePressureMonitorDTO.setSeepagePressure(seepagePressureValue);
        seepagePressureMonitorDTO.setDatetime(dateTime);
        checkWarningLevel(seepagePressureMonitorDTO);
        return seepagePressureMonitorDTO;
    }

    /**
     * 判断告警等级
     *
     * @param seepagePressureMonitorDTO
     */
    private void checkWarningLevel(SeepagePressureMonitorDTO seepagePressureMonitorDTO) {
        // 浸润水位
        Optional<SeepagePressureWarningEnum> seepagePressureFirst = DataClassificationConstant.seepagePressureWarningList.stream()
                .filter(seepagePressureWarning -> seepagePressureMonitorDTO.getSeepagePressure() >= seepagePressureWarning.getValue())
                .findFirst();
        seepagePressureMonitorDTO.setSeepagePressureWarningLevel(
                seepagePressureFirst.isEmpty() || ObjectUtil.isEmpty(seepagePressureFirst.get()) ? 0 : seepagePressureFirst.get().getWarningLevel());
    }
}
